package com.qqs.distributed.annotation;

import com.qqs.distributed.advice.AbstractCacheInterceptor;
import com.qqs.distributed.advice.AnnotationCacheAttributeSource;
import com.qqs.distributed.advice.CacheAttributeSource;
import com.qqs.distributed.advice.DefaultCacheInterceptor;
import com.qqs.distributed.advisor.BeanFactoryCacheAttributeSourceAdvisor;
import com.qqs.distributed.cache.CacheHandler;
import com.qqs.distributed.config.DistributedCacheConfigUtils;
import com.qqs.distributed.lock.LockHandlerFactory;
import com.qqs.distributed.pointcut.CacheAttributeSourcePointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Role;

import java.util.Set;

@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyDistributedCacheConfiguration {

    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public CacheAttributeSource cacheAttributeSource(Set<CacheAnnotationParser> cacheAnnotationParsers) {
        AnnotationCacheAttributeSource cacheAttributeSource = new AnnotationCacheAttributeSource(cacheAnnotationParsers);
        return cacheAttributeSource;
    }

    @Bean
    public AnnotationCacheAnnotationParsers annotationCacheAnnotationParsers(
            @Autowired(required = false) DistributedCacheProperties cacheProperties) {
        AnnotationCacheAnnotationParsers annotationParsers = new AnnotationCacheAnnotationParsers();
        annotationParsers.setCacheProperties(cacheProperties);
        return annotationParsers;
    }

    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public AbstractCacheInterceptor cacheInterceptor(
            CacheAttributeSource cacheAttributeSource,
            Set<CacheHandler> cacheHandlers,
            Set<LockHandlerFactory> lockHandlerFactories) {
        DefaultCacheInterceptor cacheInterceptor = new DefaultCacheInterceptor();
        cacheInterceptor.setCacheAttributeSource(cacheAttributeSource);
        cacheInterceptor.setCacheHandlerSet(cacheHandlers);
        cacheInterceptor.setLockHandlerFactorySet(lockHandlerFactories);
        return cacheInterceptor;
    }

    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public CacheAttributeSourcePointcut cacheAttributeSourcePointcut(CacheAttributeSource cacheAttributeSource) {
        return new CacheAttributeSourcePointcut(cacheAttributeSource);
    }

    @Bean(name = DistributedCacheConfigUtils.CACHE_ADVISOR_BEAN_NAME)
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public BeanFactoryCacheAttributeSourceAdvisor cacheAttributeSourceAdvisor(CacheAttributeSourcePointcut cacheAttributeSourcePointcut, AbstractCacheInterceptor cacheInterceptor) {
        BeanFactoryCacheAttributeSourceAdvisor advisor = new BeanFactoryCacheAttributeSourceAdvisor(cacheAttributeSourcePointcut);
        advisor.setAdvice(cacheInterceptor);
        return advisor;
    }
}
